home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-02-16 | 16.3 KB | 658 lines | [TEXT/CWIE] |
- /*
- File: AppleEvents.c
-
- Contains: The main routine
-
- Written by: Chris White, Developer Technical Support
-
- Copyright: © 1995 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- 26/01/96 GS FW Receiver
- Added ability to accept and act on Apple events from
- Folder Watcher FBA application.
-
- 12/18/95 CW First release
-
- */
-
- // System Includes
-
- #ifndef __APPLEEVENTS__
- #include <AppleEvents.h>
- #endif
-
- #include <ASRegistry.h>
- #include <Notification.h>
- #include <Icons.h>
- #include <Resources.h>
- #ifndef __SOUND__
- #include <Sound.h>
- #endif
- #include <TextUtils.h>
-
-
-
-
- // Application includes
-
- #ifndef __BAREBONES__
- #include "BareBones.h"
- #endif
-
- #ifndef __PROTOTYPES__
- #include "Prototypes.h"
- #endif
-
- #include <Resources.h>
-
-
- typedef struct MyNotificationRecord
- {
- NMRec notification;
- Str255 notificationString;
- } MyNotificationRecord, *MyNotificationPtr;
-
-
- // The events sent by the Folder Watcher FBA
- #define kFolderWatcherSuite 'wFWS'
-
- enum
- {
- kTypeFileAdded = 'wTFA', kTypeFileRemoved = 'wTFR', kTypeFileModified = 'wTFC'
- };
-
-
- const short ChangeSTRs = 200;
- enum
- {
- kAddedStr = 1, kRemovedStr, kModifiedStr
- };
-
- const short SubroutineSTRs = 300;
- enum
- {
- kAddedSub = 1, kRemovedSub, kModifiedSub
- };
-
- const short NotificationIcon = 501;
-
- // Prototypes
- pascal OSErr HandleOpenApplication( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon );
- pascal OSErr HandleQuitApplication( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon );
- pascal OSErr HandleOpenDocuments( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon );
- pascal OSErr HandlePrintDocuments( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon );
-
- pascal OSErr HandleFileAdded( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon );
- pascal OSErr HandleFileRemoved( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon );
- pascal OSErr HandleFileModified( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon );
-
- pascal OSErr HandleASSubroutine( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon );
-
- void DisplayChange( AEDesc* theDesc, short theChange );
- void DisplayChangeDesc( AEDesc* theDesc, short theChange );
- void AppendPStr( StringPtr sourceStr, StringPtr destStr );
- OSErr GetDescriptorData( const AEDesc* theDesc, Ptr destPtr, Size maxSize );
- OSErr FSSpecIsDirectory( FSSpec* theSpec, Boolean* theResult );
- OSErr GetParentDirectoryName( FSSpec* theSpec, StringPtr theName );
-
- void InitNotification( void );
- OSErr Notify( Boolean fSound, short iconID, StringPtr message );
- OSErr InstallNotification( Boolean fSound, short iconID, StringPtr message );
- OSErr RemoveNotification( void );
-
- short PositiveRandom( void );
-
-
- // Globals
- Str255 gAddedSubroutineName;
- Str255 gRemovedSubroutineName;
- Str255 gModifiedSubroutineName;
-
- NMUPP gMyNMProcPtr = NULL;
- Boolean gRemoveNotification;
- MyNotificationPtr gNotificationPtr;
- short gNumberSounds;
- SndChannelPtr gSoundChannel;
-
- #pragma segment Initialize
-
- OSErr InstallAppleEventHandlers ( void )
- {
- short err;
-
- InitNotification( );
-
- gAddedSubroutineName[0] = 0;
- gRemovedSubroutineName[0] = 0;
- gModifiedSubroutineName[0] = 0;
-
- err = AEInstallEventHandler ( kCoreEventClass, kAEOpenApplication,
- NewAEEventHandlerProc( HandleOpenApplication ), 0L, false );
- if (noErr != err) goto done;
-
- err = AEInstallEventHandler ( kCoreEventClass, kAEQuitApplication,
- NewAEEventHandlerProc( HandleQuitApplication ), 0L, false );
- if (noErr != err) goto done;
-
- err = AEInstallEventHandler ( kCoreEventClass, kAEOpenDocuments,
- NewAEEventHandlerProc (HandleOpenDocuments ), 0L, false );
- if (noErr != err) goto done;
-
- err = AEInstallEventHandler ( kCoreEventClass, kAEPrintDocuments,
- NewAEEventHandlerProc( HandlePrintDocuments ), 0L, false );
- if (noErr != err) goto done;
-
- // Events from Folder Watcher FBA
-
- err = AEInstallEventHandler ( kFolderWatcherSuite, kTypeFileAdded,
- NewAEEventHandlerProc( HandleFileAdded ), 0L, false );
- if (noErr != err) goto done;
-
- err = AEInstallEventHandler ( kFolderWatcherSuite, kTypeFileRemoved,
- NewAEEventHandlerProc( HandleFileRemoved ), 0L, false );
- if (noErr != err) goto done;
-
- err = AEInstallEventHandler ( kFolderWatcherSuite, kTypeFileModified,
- NewAEEventHandlerProc( HandleFileModified ), 0L, false );
- if (noErr != err) goto done;
-
- // Events from Script Application
-
- err = AEInstallEventHandler ( kASAppleScriptSuite, kASSubroutineEvent,
- NewAEEventHandlerProc( HandleASSubroutine ), 0L, false );
- if (noErr != err) goto done;
-
- done:
- return err;
- } // InstallAppleEventHandlers
-
-
-
- #pragma segment Core
-
- pascal OSErr HandleOpenApplication( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon )
- {
- #ifdef __MWERKS__
- #pragma unused (theAppleEvent, reply, refcon )
- #endif
-
- return noErr;
- }
-
-
-
- pascal OSErr HandleQuitApplication( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon )
- {
- #ifdef __MWERKS__
- #pragma unused (theAppleEvent, reply, refcon )
- #endif
-
- OSErr err;
-
- if ( gSoundChannel )
- {
- err = SndDisposeChannel( gSoundChannel, true );
- gSoundChannel = NULL;
- }
-
- gQuit = true;
- return noErr;
- }
-
-
-
- pascal OSErr HandleOpenDocuments( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon )
- {
- #ifdef __MWERKS__
- #pragma unused (theAppleEvent, reply, refcon )
- #endif
-
- return errAEEventNotHandled;
- }
-
-
-
- pascal OSErr HandlePrintDocuments( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon )
- {
- #ifdef __MWERKS__
- #pragma unused (theAppleEvent, reply, refcon )
- #endif
-
- return errAEEventNotHandled;
- }
-
-
- pascal OSErr HandleFileAdded( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon )
- {
- #ifdef __MWERKS__
- #pragma unused ( reply, refcon )
- #endif
-
- AEDesc aDesc = { typeNull, NULL };
- OSErr err;
-
- err = AEGetParamDesc( theAppleEvent, keyDirectObject, typeWildCard, &aDesc );
- if ( noErr != err) goto done;
-
- DisplayChange( &aDesc, kAddedStr );
-
- done:
- AEDisposeDesc( &aDesc );
-
- return err;
- }
-
-
- pascal OSErr HandleFileRemoved( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon )
- {
- #ifdef __MWERKS__
- #pragma unused ( reply, refcon )
- #endif
-
- AEDesc aDesc = { typeNull, NULL };
- OSErr err;
-
- err = AEGetParamDesc( theAppleEvent, keyDirectObject, typeWildCard, &aDesc );
- if ( noErr != err) goto done;
-
- DisplayChange( &aDesc, kRemovedStr );
-
- done:
- AEDisposeDesc( &aDesc );
-
- return err;
- }
-
-
- pascal OSErr HandleFileModified( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon )
- {
- #ifdef __MWERKS__
- #pragma unused ( reply, refcon )
- #endif
-
- AEDesc aDesc = { typeNull, NULL };
- OSErr err;
-
- err = AEGetParamDesc( theAppleEvent, keyDirectObject, typeWildCard, &aDesc );
- if ( noErr != err) goto done;
-
- DisplayChange( &aDesc, kModifiedStr );
-
- done:
- AEDisposeDesc( &aDesc );
-
- return err;
- }
-
-
- // AppleScript will send this type of event if you structure your call like a subroutine.
- // This way you can accept the events without AppleScript checking out your terminology
- // through the 'aete' resource.
-
- pascal OSErr HandleASSubroutine( AppleEvent *theAppleEvent, AppleEvent *reply, long refcon )
- {
- #ifdef __MWERKS__
- #pragma unused ( reply, refcon )
- #endif
-
- Str255 subroutineStr;
- DescType typeCode;
- Size actualSize;
- AEDesc aDesc = { typeNull, NULL };
- OSErr err;
-
-
- err = AEGetParamPtr( theAppleEvent, keyASSubroutineName, typeChar,
- &typeCode, &subroutineStr[1], 255, &actualSize );
- if ( noErr != err ) goto done;
- subroutineStr[0] = actualSize;
-
- err = AEGetParamDesc( theAppleEvent, keyDirectObject, typeWildCard, &aDesc );
- if ( noErr != err ) goto done;
-
- // Check we've read the resources in
- if ( ! gAddedSubroutineName[0] )
- GetIndString( gAddedSubroutineName, SubroutineSTRs, kAddedSub );
-
- if ( ! gRemovedSubroutineName[0] )
- GetIndString( gRemovedSubroutineName, SubroutineSTRs, kRemovedSub );
-
- if ( ! gModifiedSubroutineName[0] )
- GetIndString( gModifiedSubroutineName, SubroutineSTRs, kModifiedSub );
-
- if ( EqualString( subroutineStr, gAddedSubroutineName , false, false ))
- DisplayChange( &aDesc, kAddedStr );
- else if ( EqualString( subroutineStr, gRemovedSubroutineName , false, false ))
- DisplayChange( &aDesc, kRemovedStr );
- else if ( EqualString( subroutineStr, gModifiedSubroutineName , false, false ))
- DisplayChange( &aDesc, kModifiedStr );
-
- done:
- AEDisposeDesc( &aDesc );
-
- return err;
- }
-
-
- // This routine takes care of lists
-
- void DisplayChange( AEDesc* theDesc, short theChange )
- {
- AEDesc aDesc = { typeNull, NULL };
- long aCount,
- anIndex;
- AEKeyword anAEKeyword;
- OSErr err;
-
- switch ( theDesc->descriptorType )
- {
- case typeAEList: // Handle lists
- err = AECountItems( theDesc, &aCount );
- if ( noErr != err ) goto done;
-
- for (anIndex = 1; anIndex <= aCount; anIndex++ )
- {
- err = AEGetNthDesc( theDesc, anIndex, typeWildCard, &anAEKeyword, &aDesc );
- if ( noErr != err ) goto done;
-
- DisplayChange( &aDesc, theChange );
-
- (void)AEDisposeDesc( &aDesc );
- }
- break;
-
- default:
- DisplayChangeDesc( theDesc, theChange );
- }
-
- done:
- (void)AEDisposeDesc( &aDesc );
- }
-
-
- // Add the change to our list and notify user of change.
-
- void DisplayChangeDesc( AEDesc* theDesc, short theChange )
- {
- Str255 displayStr,
- tempStr;
- AEDesc anFSSpecDesc = { typeNull, NULL };
- FSSpec anFSSpec;
- Boolean fDirectory;
- unsigned long now;
- OSErr err;
-
- err = AECoerceDesc( theDesc, typeFSS, &anFSSpecDesc );
- if ( noErr != err ) goto done;
-
- err = GetDescriptorData( &anFSSpecDesc, (Ptr)&anFSSpec, sizeof( anFSSpec ) );
- if ( noErr != err ) goto done;
-
- err = FSSpecIsDirectory( &anFSSpec, &fDirectory);
- if ( noErr != err ) goto done;
-
- displayStr[0] = 0; // Empty the string
-
- if ( ! fDirectory ) // If it isn't a directory then add
- { // the directory name before it.
- err = GetParentDirectoryName( &anFSSpec, tempStr );
- if ( noErr != err ) goto done;
- AppendPStr( tempStr, displayStr );
- AppendPStr( "\p:", displayStr );
- }
-
- AppendPStr( anFSSpec.name, displayStr ); // Add the folder/file name
- if ( fDirectory )
- AppendPStr( "\p:", displayStr ); // If a directory show by sticking colon after
-
- GetIndString( tempStr, ChangeSTRs, theChange );
- AppendPStr( "\p\t", displayStr ); // Add a tab
- AppendPStr( tempStr, displayStr ); // Add Added/Removed/Modified
-
- GetDateTime( &now );
- TimeString( now, false, tempStr, NULL );
- AppendPStr( "\p\t", displayStr ); // Add a tab
- AppendPStr( tempStr, displayStr ); // Add Time
-
- DateString( now, abbrevDate, tempStr, NULL );
- AppendPStr( "\p\t", displayStr ); // Add a tab
- AppendPStr( tempStr, displayStr ); // Add Date
-
- AddToListContent( displayStr );
-
- Notify( true, NotificationIcon, NULL );
-
- done:
- AEDisposeDesc( &anFSSpecDesc );
- }
-
-
- // Just a pascal string concatenation routine.
- // Doesn't check for 255 character limit.
-
- void AppendPStr( StringPtr sourceStr, StringPtr destStr )
- {
- BlockMoveData( &sourceStr[1], &destStr[1] + destStr[0], sourceStr[0] );
- destStr[0] += sourceStr[0];
- }
-
-
- // Get the data out of the data handle of the descriptor.
-
- OSErr GetDescriptorData( const AEDesc* theDesc, Ptr destPtr, Size maxSize )
- {
- Size copySize;
- OSErr err = noErr;
-
- if ( typeNull == theDesc->descriptorType || ! theDesc->dataHandle )
- return( errAENotAEDesc );
-
- copySize = GetHandleSize( (Handle)theDesc->dataHandle );
- if ( copySize <= maxSize )
- {
- HLock( (Handle)theDesc->dataHandle );
- BlockMoveData( *theDesc->dataHandle, destPtr, copySize );
- HUnlock( (Handle)theDesc->dataHandle );
- }
- else
- err = errAECorruptData;
-
- return err;
- } // GetDescriptorData
-
-
- // Check to see if FSSpec is for a directory.
-
- OSErr FSSpecIsDirectory( FSSpec* theSpec, Boolean* theResult )
- {
- CInfoPBRec aPB;
- OSErr err;
-
- aPB.dirInfo.ioNamePtr = theSpec->name;
- aPB.dirInfo.ioVRefNum = theSpec->vRefNum;
- aPB.dirInfo.ioDrDirID = theSpec->parID;
- aPB.dirInfo.ioFDirIndex = 0; // Use ioNamePtr and ioDirID
- aPB.dirInfo.ioACUser = 0; // Clear it before calling GetCatInfo
- err = PBGetCatInfo( &aPB, false );
-
- if ( noErr == err )
- *theResult = ( aPB.dirInfo.ioFlAttrib & ioDirMask );
-
- return err;
- }
-
-
- // Get parent directory name for an FSSpec.
-
- OSErr GetParentDirectoryName( FSSpec* theSpec, StringPtr theName )
- {
- CInfoPBRec aPB;
- OSErr err;
-
- aPB.dirInfo.ioNamePtr = theName;
- aPB.dirInfo.ioVRefNum = theSpec->vRefNum;
- aPB.dirInfo.ioDrDirID = theSpec->parID;
- aPB.dirInfo.ioFDirIndex = -1; // Get info about the directory
- aPB.dirInfo.ioACUser = 0; // Clear it before calling GetCatInfo
- err = PBGetCatInfo( &aPB, false );
-
- return err;
- }
-
-
- // Call this once during application initialization
-
- void InitNotification( void )
- {
- OSErr err;
-
- gRemoveNotification = false;
- GetDateTime( (unsigned long *)&qd.randSeed );
- gNumberSounds = Count1Resources( soundListRsrc );
- gSoundChannel = NULL;
- err = SndNewChannel( &gSoundChannel, 0, 0, NULL );
- }
-
-
- // This routine checks whether or not the notification
- // is already displayed. If it isn't then it puts up
- // a notification.
-
- OSErr Notify( Boolean fSound, short iconID, StringPtr message )
- {
- Handle sndHandle;
- OSErr err = noErr;
-
- fSound = ( fSound && ( gNumberSounds > 0 ) );
-
- if ( gRemoveNotification && fSound)
- { // We'll still play the sounds because I like it.
- // Note that this may drive the user crazy.
- sndHandle = Get1IndResource( soundListRsrc, ( PositiveRandom( ) % gNumberSounds ) + 1 );
- HNoPurge( sndHandle );
- err = SndPlay( gSoundChannel, (SndListHandle)sndHandle, true );
- }
- else
- err = InstallNotification( true, iconID, message );
-
- return err;
- }
-
-
- OSErr InstallNotification( Boolean fSound, short iconID, StringPtr message )
- {
- Handle anIconSuite;
- Handle ics8Handle,
- ics4Handle,
- icsBWHandle;
- Handle sndHandle;
- OSErr err;
-
- gNotificationPtr = (MyNotificationPtr)NewPtrClear( sizeof( MyNotificationRecord ) );
- err = MemError( );
- if (noErr != err || ! gNotificationPtr ) goto done;
-
- gNotificationPtr->notification.qType = nmType;
- gNotificationPtr->notification.nmMark = 1; // Put a mark next to our application
- // in the application menu.
- if ( iconID )
- {
- err = NewIconSuite(&anIconSuite);
- if (noErr != err ) goto done;
-
- ics8Handle = Get1Resource( kSmall8BitData, NotificationIcon );
- HNoPurge( ics8Handle );
- err = AddIconToSuite( ics8Handle, anIconSuite, kSmall8BitData );
- if (noErr != err ) goto done;
-
- ics4Handle = Get1Resource( kSmall4BitData, NotificationIcon );
- HNoPurge( ics4Handle );
- err = AddIconToSuite( ics4Handle, anIconSuite, kSmall4BitData );
- if (noErr != err ) goto done;
-
- icsBWHandle = Get1Resource( kSmall1BitMask, NotificationIcon );
- HNoPurge( icsBWHandle );
- err = AddIconToSuite( icsBWHandle, anIconSuite, kSmall1BitMask );
- if (noErr != err ) goto done;
-
- gNotificationPtr->notification.nmIcon = anIconSuite;
- }
- else
- gNotificationPtr->notification.nmIcon = NULL;
-
- // handle to sound record
- if ( fSound )
- {
- sndHandle = Get1IndResource( soundListRsrc, ( PositiveRandom( ) % gNumberSounds ) + 1 );
- HNoPurge( sndHandle );
- gNotificationPtr->notification.nmSound = sndHandle;
- }
- else
- gNotificationPtr->notification.nmSound = NULL;
-
- // string to appear in alert
- if ( message ) // Send NULL StringPtr if no alert wanted
- {
- BlockMoveData( message, gNotificationPtr->notificationString, message[0] + 1 );
- gNotificationPtr->notification.nmStr = gNotificationPtr->notificationString;
- }
- else
- gNotificationPtr->notification.nmStr = NULL;
-
- // pointer to response routine
- gNotificationPtr->notification.nmResp = NULL; // gMyNMProcPtr;
- gNotificationPtr->notification.nmRefCon = 0; // SetCurrentA5( ); // Copy current A5
-
- err = NMInstall( (NMRecPtr)gNotificationPtr );
- if ( noErr == err )
- gRemoveNotification = true;
-
- done:
- if ( noErr != err ) // If there was an error then clean up the memory
- {
- if ( gNotificationPtr->notification.nmIcon )
- err = DisposeIconSuite( gNotificationPtr->notification.nmIcon, false );
-
- DisposPtr( (Ptr)gNotificationPtr );
- gNotificationPtr = NULL;
- }
-
- return err;
- }
-
-
- // If there is a notification running then this routine removes it
- // and disposes of the associated memory.
-
- OSErr RemoveNotification( void )
- {
- OSErr err = noErr;
-
- if ( gRemoveNotification )
- {
- err = NMRemove( (NMRecPtr)gNotificationPtr );
-
- if ( gNotificationPtr->notification.nmIcon )
- err = DisposeIconSuite( gNotificationPtr->notification.nmIcon, false );
-
- DisposPtr( (Ptr)gNotificationPtr );
- gNotificationPtr = NULL;
-
- gRemoveNotification = false; // Reset the flag
- }
-
- return err;
- } // RemoveNotification
-
-
- short PositiveRandom( void )
- {
- short aRandom = Random( );
-
- if ( aRandom >= 0 )
- return aRandom;
- else
- return aRandom * -1;
- }